///////////////////////////////////////////////////////////////////////////////
//	FILENAME:	GIFWriting.m
//	SUMMARY:	Implementation of a GIFWriting category to NXImage
//	SUPERCLASS:	Object:NXImage(GIFWriting)
//	INTERFACE:	None
//	AUTHOR:		Rohit Khare
//	COPYRIGHT:	(c) 1994 California Institure of Technology, eText Project
///////////////////////////////////////////////////////////////////////////////
//  IMPLEMENTATION COMMENTS
//		This code uses the netPBM distribution. Currently, it creates a temp
//	tiff (uncompressed) in /tmp and then opens a pipe to a string of netPBM
//	filters assumed to be located in [NXApp mainBundle], then copies those
//	bytes to the target stream.
//		In the future, we should rework the code to directly access the netPBM
//	and libTIFF libraries. Transparency support would also be mondo cool.
///////////////////////////////////////////////////////////////////////////////
//	HISTORY
//	10/30/94:	Extended to use OmniImageFilter as first resort (for HP-PA).
//	07/16/94:	Created. Derived from netPBM.
///////////////////////////////////////////////////////////////////////////////

#import "eTextKernel.h"
#import "GIFWriting.h"
#import "_FormatWritingImageView.h"
#import <machkit/NXData.h>

@implementation NXImage (GIFWriting)
- writeGIFtoPath_Poskanzer:(const char *)destPath
{
	char	tempPath[MAXPATHLEN];
	char	cmd[4*MAXPATHLEN];
	const char	*appPath;
	id	iv;

	iv = [_FormatWritingImageView new];
	[iv useImage:self];
	sprintf(tempPath, "/tmp/eTextGifConversion.%x.tiff", [NXApp uniqueID]);
	[iv dumpTIFF:tempPath];
	
	// no fs flag; I don't think ppmquant improves colors with it.
	// Ideally, we'd run ppmquant iff we really needed to. but for simplicity
	// we always call it. Does this cause aesthetic errors?
	NXLogError("GIFWriting: generating %s", destPath);
	appPath = [[NXBundle mainBundle] directory];
	sprintf(cmd,"\"%s/tifftopnm\" \"%s\" | \"%s/ppmquant\" 256 | \"%s/ppmtogif\" > \"%s\"",
			appPath, tempPath, appPath, appPath, destPath);
	system(cmd);
	unlink(tempPath);
	return self;
}
- writeGIFtoPath:(const char *)destPath
{
	NXAtom *OIFtypes;
	static NXAtom gifType = NULL;
	if (!gifType) gifType = NXUniqueString("image format gif");
	
	// Can OIF handle this?
	OIFtypes = [Pasteboard typesFilterableTo:gifType];
	
	if (OIFtypes && *OIFtypes) {
		id conversionPB,data;
		NXStream *t;
		char *tiffbytes; int len, maxlen;
		
		// Add TIFF data to a PBoard
		t = NXOpenMemory(NULL,0,NX_READWRITE);
		[self writeTIFF:t];
		NXGetMemoryBuffer(t, &tiffbytes, &len, &maxlen);
		data = [[NXData alloc] initWithData:(void *)tiffbytes size:maxlen dealloc:YES];
		conversionPB = [Pasteboard newByFilteringData:data ofType:NXTIFFPboardType];
		
		if ([conversionPB findAvailableTypeFrom:&gifType num:1]) {
			NXStream *s = [conversionPB readTypeToStream:gifType];
			if (s) {
				NXSaveToFile(s, destPath);
				NXCloseMemory(s, NX_FREEBUFFER);
			} else {
				// OK, try the Poskanzer pipeline
				[self writeGIFtoPath_Poskanzer:destPath];
			}
		} else {
			// OK, try the Poskanzer pipeline
			[self writeGIFtoPath_Poskanzer:destPath];
		}

		// Attempt to free the data from VM.
		[conversionPB free];
		[data free];
		NXCloseMemory(t, NX_FREEBUFFER);
		free(OIFtypes);
	} else {
		// OK, try the Poskanzer pipeline
		[self writeGIFtoPath_Poskanzer:destPath];
	}
	return self;
}
@end